#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/time.h>

/**
 * 信号 ： kill
 * 父进程杀死子进程，也可以杀自己
 * @return
 */
//int main() {
//    pid_t pid = -1;
//
//    //创建子进程
//    pid = fork();
//    if(-1 == pid){
//        perror("fork");
//        return 1;
//    }
//    //子进程
//    if(0 == pid){
//        while (1){
//            printf("子进程在运行\n");
//            sleep(1);
//        }
//        exit(0);
//    }
//    //父进程
//    else{
//        sleep(3);
//        printf("父进程杀子进程\n");
//        kill(pid,SIGTERM);
//        printf("父进程结束\n");
//    }
//    return 0;
//}

/**
 * 信号 ： raise
 * 给自己发指定信号
 * @return
 */
//int main() {
//    int i = 1;
//    while(1){
//        printf("working %d\n", i);
//        if(i == 4){
//            // 进程自杀
//            //kill(getpid(),SIGTERM);
//            raise(SIGTERM);
//        }
//        i ++;
//        sleep(1);
//    }
//    return 0;
//}

/**
 * 信号 ： abort
 * 给自己发送异常信号 SIGABRT 并产生core文件等价于 kill(getpid(), SIGABRT)
 * @return
 */
//int main() {
//    int i = 1;
//    while(1){
//        printf("working %d\n", i);
//        if(i == 4){
//            //给自己发送一个 6 的信号，默认的行为就是终止进程
//            abort();
//        }
//        i ++;
//        sleep(1);
//    }
//    return 0;
//}

/**
 * 信号 ： alarm（闹钟） 秒为单位
 * 默认是终止进程
 * @return
 */
//int main() {
//    unsigned int ret = 0;
//    //设置闹钟 5秒中后就超时就发送对应的信号
//    ret = alarm(5);
//    printf("ret = %u\n",ret);
//    sleep(2);
//    // 返回旧闹钟剩余的秒数，数遍设置了新的闹钟
//    ret = alarm(3);
//    printf("ret = %u\n",ret);
//    printf("按下任意键位结束。。。\n");
//    getchar();
//    return 0;
//}

/**
 * 信号 ： setitimer（定时器） 可以用秒或者微秒为单位，可以实现周期定时 可以替代 alarm
 * 当前代码为 让进程终止，暂时没有周期触发的效果
 * @return
 */
//int main() {
//    int ret = -1;
//    struct itimerval tmo;
//    // 第一次触发时间
//    tmo.it_value.tv_sec = 3;
//    tmo.it_value.tv_usec = 0;
//    // 后续触发周期
//    tmo.it_interval.tv_sec = 2;
//    tmo.it_interval.tv_usec = 0;
//
//    ret = setitimer(ITIMER_REAL,&tmo,NULL);
//    if(-1 == ret){
//        perror("setitimer");
//        return 1;
//    }
//
//    // 进程到时间后会停止
//    printf("按下任意键位结束\n");
//    getchar();
//    return 0;
//}

/**
 * 信号处理函数
 */

void fun1(int signum){
    printf("fun1 catch signal %d \n",signum);
}

void fun2(int signum){
    printf("fun2 catch signal %d \n",signum);
}

/**
 * 信号 ： signal
 * 信号注册函数 尽量避免使用，推荐用 sigaction
 * @return
 */
//int main() {
//
//    // 信号注册 ctrl+c
//    signal(SIGINT,fun1);
//    // 信号注册 ctrl+'\' 这个信号不能出现 sleep
//    signal(SIGQUIT,fun2);
//
//    while(1){
//        //sleep(1);
//    }
//    return 0;
//}

/**
 * 信号 ： setitimer（定时器） 可以用秒或者微秒为单位，可以实现周期定时 可以替代 alarm
 * 当前代码为 信号捕捉
 *
 * @return
 */
int main() {
    int ret = -1;
    struct itimerval tmo;
    // 第一次触发时间
    tmo.it_value.tv_sec = 3;
    tmo.it_value.tv_usec = 0;
    // 后续触发周期
    tmo.it_interval.tv_sec = 2;
    tmo.it_interval.tv_usec = 0;

    // 设置信号
    signal(SIGALRM,fun1);

    ret = setitimer(ITIMER_REAL,&tmo,NULL);
    if(-1 == ret){
        perror("setitimer");
        return 1;
    }

    // 进程到时间后会停止
    printf("按下任意键位结束\n");
    getchar();
    return 0;
}